package com.cskaoyan._01abstractclazz._01introduction;

/**
 * @description:
 * @author: 景天
 * @date: 2023/2/10 17:20
 **/
/*
从以下两个角度分析：

1. 从代码角度上，有没有冗余代码？
2. 从设计角度上，在这个案例中，会存在一个动物对象吗？

分析一下

1. 单纯从代码角度上，有没有冗余代码？
   实际上是有的。从方法调用的角度考虑，Animal类当中的shout方法从来没有被调用过。
   该方法单纯就是让子类继承并重写的，它实际上没有被调用的需求。
   从最理想的角度上来说，它的方法体是可以去掉的，仅保留一个声明让子类去重写就可以了。

2. 当然代码多几行少几行并不重要，重要是：
从设计角度出发，Animal类是一个抽象的概念，用于指代所有动物。
程序中根本不需要创建它的对象。而且对于一个抽象的概念，也不应该、也不可能去描述它的行为。

综上，我们提出两个改进的方向：

1. Animal类就是作为顶层抽象祖先类而存在的，不需要创建对象，于是干脆不要创建对象了。
2. Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。

使用抽象类

抽象方法的语法:
    权限修饰符 abstract 方法返回值类型 方法名(形参列表);
    说明:
        抽象方法没有方法体,不用实现.
        抽象方法要在抽象类中
抽象类语法:
    权限修饰符 abstract 类名{类体}
    说明:
        权限修饰符:public 或者默认
        抽象类的命名:一定要大驼峰, 一般习惯命名AbstractXxxx 或者BaseXxxx
        抽象类不可以创建对象
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstract; cannot be instantiated(实例化)
        // Animal a = new Animal();
        Animal animal;
        animal = new Cat();
        animal.shout();

        animal = new Dog();
        animal.shout();
    }
}

abstract class Animal {
    // 抽象方法 必须要在抽象类中
    // Abstract method in non-abstract class
    public abstract void shout();
}
class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}
class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}